package com.school.sports.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.List;

/**
 * 消息表实体类
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("message")
public class Message {

    @TableId(type = IdType.AUTO)
    private Long id;

    /**s
     * 用户ID
     */
    @NotNull(message = "用户ID不能为空")
    private Long userId;

    /**
     * 消息标题
     */
    @NotBlank(message = "消息标题不能为空")
    @Size(max = 200, message = "消息标题长度不能超过200个字符")
    private String title;

    /**
     * 消息内容
     */
    @NotBlank(message = "消息内容不能为空")
    @Size(max = 2000, message = "消息内容长度不能超过2000个字符")
    private String content;

    /**
     * 消息类型：系统通知、审核结果、赛程变更、成绩公示、获奖通知、紧急通知
     */
    @NotNull(message = "消息类型不能为空")
    private String type;

    /**
     * 是否已读：0-未读，1-已读
     */
    private Integer isRead;

    /**
     * 创建时间
     */
    private LocalDateTime createdAt;

    /**
     * 发送者ID（系统消息为null）
     */
    @TableField(exist = false)
    private Long senderId;

    /**
     * 发送者姓名（关联查询时使用）
     */
    @TableField(exist = false)
    private String senderName;

    /**
     * 用户对象（关联查询时使用）
     */
    @TableField(exist = false)
    private User user;

    /**
     * 发送者对象（关联查询时使用）
     */
    @TableField(exist = false)
    private User sender;

    /**
     * 消息优先级（1-高，2-中，3-低）
     */
    @TableField(exist = false)
    private Integer priority;

    /**
     * 消息状态（0-正常，1-已撤回）
     */
    @TableField(exist = false)
    private Integer status;

    /**
     * 阅读时间
     */
    @TableField(exist = false)
    private LocalDateTime readAt;

    /**
     * 消息链接（点击消息后跳转的URL）
     */
    @TableField(exist = false)
    private String linkUrl;

    /**
     * 扩展数据（JSON格式）
     */
    @TableField(exist = false)
    private String extraData;

    /**
     * 消息类型枚举
     */
    public enum MessageType {
        SYSTEM("系统通知"),
        AUDIT_RESULT("审核结果"),
        SCHEDULE_CHANGE("赛程变更"),
        SCORE_PUBLISHED("成绩公示"),
        AWARD_NOTIFICATION("获奖通知"),
        URGENT("紧急通知"),
        REMINDER("提醒通知"),
        ANNOUNCEMENT("公告通知"),
        TASK_ASSIGNMENT("任务分配"),
        EVALUATION("评价通知");

        private final String displayName;

        MessageType(String displayName) {
            this.displayName = displayName;
        }

        public String getDisplayName() {
            return displayName;
        }

        /**
         * 根据显示名称获取枚举值
         */
        public static MessageType fromDisplayName(String displayName) {
            for (MessageType type : MessageType.values()) {
                if (type.getDisplayName().equals(displayName)) {
                    return type;
                }
            }
            return null;
        }
    }

    /**
     * 消息状态枚举
     */
    public enum MessageStatus {
        NORMAL("正常"),
        RECALLED("已撤回"),
        DELETED("已删除");

        private final String displayName;

        MessageStatus(String displayName) {
            this.displayName = displayName;
        }

        public String getDisplayName() {
            return displayName;
        }

        /**
         * 根据显示名称获取枚举值
         */
        public static MessageStatus fromDisplayName(String displayName) {
            for (MessageStatus status : MessageStatus.values()) {
                if (status.getDisplayName().equals(displayName)) {
                    return status;
                }
            }
            return null;
        }
    }

    /**
     * 设置消息类型
     */
    public void setType(String type) {
        this.type = type;
        // 根据类型设置优先级
        setPriorityByType();
    }

    /**
     * 获取消息类型显示名称
     */
    public String getTypeDisplayName() {
        MessageType typeEnum = MessageType.fromDisplayName(this.type);
        return typeEnum != null ? typeEnum.getDisplayName() : this.type;
    }

    /**
     * 检查是否为系统消息
     */
    public boolean isSystemMessage() {
        return MessageType.SYSTEM.getDisplayName().equals(this.type);
    }

    /**
     * 检查是否为紧急消息
     */
    public boolean isUrgentMessage() {
        return MessageType.URGENT.getDisplayName().equals(this.type);
    }

    /**
     * 检查是否为审核结果消息
     */
    public boolean isAuditResultMessage() {
        return MessageType.AUDIT_RESULT.getDisplayName().equals(this.type);
    }

    /**
     * 检查是否为获奖通知
     */
    public boolean isAwardNotification() {
        return MessageType.AWARD_NOTIFICATION.getDisplayName().equals(this.type);
    }

    /**
     * 标记为已读
     */
    public void markAsRead() {
        this.isRead = 1;
        this.readAt = LocalDateTime.now();
    }

    /**
     * 标记为未读
     */
    public void markAsUnread() {
        this.isRead = 0;
        this.readAt = null;
    }

    /**
     * 检查是否已读
     */
    public boolean isRead() {
        return Integer.valueOf(1).equals(this.isRead);
    }

    /**
     * 检查是否未读
     */
    public boolean isUnread() {
        return !isRead();
    }

    /**
     * 撤回消息
     */
    public void recall() {
        this.status = 1; // 已撤回
    }

    /**
     * 检查是否已撤回
     */
    public boolean isRecalled() {
        return Integer.valueOf(1).equals(this.status);
    }

    /**
     * 检查消息是否有效
     */
    public boolean isValid() {
        return userId != null && title != null && !title.trim().isEmpty()
                && content != null && !content.trim().isEmpty() && type != null;
    }

    /**
     * 获取消息优先级显示名称
     */
    public String getPriorityDisplay() {
        if (priority == null) {
            priority = 2; // 默认中等优先级
        }

        switch (priority) {
            case 1: return "高";
            case 2: return "中";
            case 3: return "低";
            default: return "中";
        }
    }

    /**
     * 根据类型设置优先级
     */
    private void setPriorityByType() {
        if (type == null) {
            this.priority = 2;
            return;
        }

        MessageType messageType = MessageType.fromDisplayName(type);
        if (messageType == null) {
            this.priority = 2;
            return;
        }

        switch (messageType) {
            case URGENT:
                this.priority = 1;
                break;
            case SYSTEM:
            case AWARD_NOTIFICATION:
                this.priority = 1;
                break;
            case AUDIT_RESULT:
            case SCHEDULE_CHANGE:
            case SCORE_PUBLISHED:
                this.priority = 2;
                break;
            default:
                this.priority = 3;
                break;
        }
    }

    /**
     * 获取消息状态显示名称
     */
    public String getStatusDisplay() {
        if (status == null) {
            return MessageStatus.NORMAL.getDisplayName();
        }

        switch (status) {
            case 0: return MessageStatus.NORMAL.getDisplayName();
            case 1: return MessageStatus.RECALLED.getDisplayName();
            default: return MessageStatus.NORMAL.getDisplayName();
        }
    }

    /**
     * 获取消息类型标签样式（用于前端显示）
     */
    public String getTypeTagType() {
        MessageType messageType = MessageType.fromDisplayName(this.type);
        if (messageType == null) return "info";

        switch (messageType) {
            case URGENT: return "danger";
            case SYSTEM: return "primary";
            case AWARD_NOTIFICATION: return "success";
            case AUDIT_RESULT: return "warning";
            case SCHEDULE_CHANGE: return "warning";
            case SCORE_PUBLISHED: return "success";
            default: return "info";
        }
    }

    /**
     * 获取优先级标签样式
     */
    public String getPriorityTagType() {
        if (priority == null) return "info";

        switch (priority) {
            case 1: return "danger";
            case 2: return "warning";
            case 3: return "info";
            default: return "info";
        }
    }

    /**
     * 获取消息创建时间显示
     */
    public String getTimeDisplay() {
        if (createdAt == null) return "未知时间";

        LocalDateTime now = LocalDateTime.now();
        long minutes = ChronoUnit.MINUTES.between(createdAt, now);
        long hours = ChronoUnit.HOURS.between(createdAt, now);
        long days = ChronoUnit.DAYS.between(createdAt, now);

        if (minutes < 1) {
            return "刚刚";
        } else if (minutes < 60) {
            return minutes + "分钟前";
        } else if (hours < 24) {
            return hours + "小时前";
        } else if (days < 7) {
            return days + "天前";
        } else {
            return createdAt.toString().substring(0, 10); // 只显示日期部分
        }
    }

    /**
     * 获取消息摘要（截取内容前50个字符）
     */
    public String getSummary() {
        if (content == null || content.trim().isEmpty()) {
            return "无内容";
        }

        if (content.length() <= 50) {
            return content;
        }

        return content.substring(0, 50) + "...";
    }

    /**
     * 获取消息完整显示信息
     */
    public String getFullDisplay() {
        StringBuilder display = new StringBuilder();
        display.append("标题：").append(title != null ? title : "无标题").append("\n");
        display.append("类型：").append(getTypeDisplayName()).append("\n");
        display.append("优先级：").append(getPriorityDisplay()).append("\n");
        display.append("状态：").append(isRead() ? "已读" : "未读").append("\n");
        display.append("创建时间：").append(createdAt != null ? createdAt.toString() : "未知").append("\n");
        display.append("内容：").append(content != null ? content : "无内容");

        if (senderName != null) {
            display.append("\n发送者：").append(senderName);
        }

        if (isRead() && readAt != null) {
            display.append("\n阅读时间：").append(readAt.toString());
        }

        return display.toString();
    }

    /**
     * 检查消息是否需要提醒
     */
    public boolean needsReminder() {
        // 紧急消息且未读
        return isUrgentMessage() && isUnread();
    }

    /**
     * 检查消息是否过期（超过7天未读）
     */
    public boolean isExpired() {
        if (createdAt == null) return false;
        return ChronoUnit.DAYS.between(createdAt, LocalDateTime.now()) > 7 && isUnread();
    }

    /**
     * 获取消息图标
     */
    public String getIcon() {
        MessageType messageType = MessageType.fromDisplayName(this.type);
        if (messageType == null) return "message";

        switch (messageType) {
            case URGENT: return "warning";
            case SYSTEM: return "setting";
            case AWARD_NOTIFICATION: return "trophy";
            case AUDIT_RESULT: return "document";
            case SCHEDULE_CHANGE: return "calendar";
            case SCORE_PUBLISHED: return "medal";
            case REMINDER: return "bell";
            case ANNOUNCEMENT: return "notification";
            case TASK_ASSIGNMENT: return "user";
            case EVALUATION: return "star";
            default: return "message";
        }
    }

    /**
     * 从关联对象同步字段信息
     */
    public void syncFieldsFromObjects() {
        if (user != null) {
            // 同步用户相关信息
        }

        if (sender != null) {
            this.senderName = sender.getRealName();
        }

        // 根据类型设置优先级
        setPriorityByType();
    }

    /**
     * 获取所有可能的消息类型
     */
    public static List<String> getAllMessageTypes() {
        return Arrays.asList(
                MessageType.SYSTEM.getDisplayName(),
                MessageType.AUDIT_RESULT.getDisplayName(),
                MessageType.SCHEDULE_CHANGE.getDisplayName(),
                MessageType.SCORE_PUBLISHED.getDisplayName(),
                MessageType.AWARD_NOTIFICATION.getDisplayName(),
                MessageType.URGENT.getDisplayName(),
                MessageType.REMINDER.getDisplayName(),
                MessageType.ANNOUNCEMENT.getDisplayName(),
                MessageType.TASK_ASSIGNMENT.getDisplayName(),
                MessageType.EVALUATION.getDisplayName()
        );
    }

    /**
     * 检查消息是否可以撤回
     */
    public boolean canRecall() {
        // 只有未读且创建时间不超过5分钟的消息可以撤回
        if (isRead()) return false;
        if (createdAt == null) return false;
        return ChronoUnit.MINUTES.between(createdAt, LocalDateTime.now()) <= 5;
    }

    /**
     * 获取消息操作历史
     */
    public String getOperationHistory() {
        StringBuilder history = new StringBuilder();
        history.append("创建时间：").append(createdAt != null ? createdAt.toString() : "未知");

        if (isRead() && readAt != null) {
            history.append("\n阅读时间：").append(readAt.toString());
        }

        if (isRecalled()) {
            history.append("\n撤回时间：").append(LocalDateTime.now().toString());
        }

        return history.toString();
    }

    /**
     * 检查消息是否需要推送通知
     */
    public boolean shouldPushNotification() {
        // 紧急消息和系统消息需要推送
        return isUrgentMessage() || isSystemMessage();
    }

    /**
     * 获取推送通知内容
     */
    public String getPushContent() {
        if (isUrgentMessage()) {
            return "【紧急】" + title;
        } else {
            return title;
        }
    }

    /**
     * 检查消息是否包含链接
     */
    public boolean hasLink() {
        return linkUrl != null && !linkUrl.trim().isEmpty();
    }

    /**
     * 获取消息关键词
     */
    public List<String> getKeywords() {
        if (title == null && content == null) {
            return Arrays.asList();
        }

        String text = (title != null ? title : "") + " " + (content != null ? content : "");
        // 简单的关键词提取，实际可以使用更复杂的算法
        String[] words = text.split("[\\s，,。、；;！！？?]");
        return Arrays.asList(words)
                .stream()
                .filter(word -> word != null && word.trim().length() > 1)
                .distinct()
                .limit(5)
                .collect(java.util.stream.Collectors.toList());
    }
}